The Structured Query Language (SQL) is a language designed for the management of relational databases. SQL injections vulnerabilities occur when user input is passed unsanitised to an SQL query and allow an attacker to alter the queries that an application sends to its database. This may enable the attacker to view data which they usually shouldn't have access to, edit this data arbitrarily, or modify the actual database in ways that they shouldn't be able to.
There are three main types of SQL injections:
In-band - the vulnerable application provides the query's result with the application-returned value
Out-of-band - the results from the attack are exfiltrated using a different channel than the one the query was issued through such as through an HTTP connection for sending results to a different web server or DNS tunneling
Blind (Inferential) - they rely on changes in the behaviour of the database or application in order to extract information, since the actual data isn't sent back to the attacker
Testing for SQL injections is fairly straightforward but can be an onerous task. It constitutes inserting a single quote and then a payload such as ' SQL PAYLOAD
into any user input field and observing the subsequent behaviour.
It comes in handy to append comment sequences such as `-- -` to your payloads so that any parts of the query which come after the injection point will not interfere with the injection. This works on all database engines.
If the result from the query is directly embedded into the web page, then this is the simplest and most powerful type of in-band SQL injection because it provides us with a direct way to see the output of the query and exfiltrate data. When this type of SQL injection is present, one can use Union Injection to easily obtain information from the database.
We can use [this](https://portswigger.net/web-security/sql-injection/lab-retrieve-hidden-data) PortSwigger lab to showcase a simple SQL injection. We notice that we can filter our search using one of the buttons on the home page under "Refine your search".
![](Resources/Images/Example%20Simple%20SQL%20Injection%20Home%20Page.png)
Clicking on one of the filter buttons produces a `GET` request and we can try to manipulate the `category` parameter.
![](Resources/Images/Example%20Simple%20SQL%20Injection%20Exploited.png)
Indeed, using the payload `' or 1=1 -- -` as the value for `category` reveals some products which were hidden before.
Blind SQL injection occurs when an application is vulnerable to SQL injection, but the response page does not include the queried data or any specific database errors.
The first way to test for these is to use boolean conditions via the AND
operator. If we suspect that a field is vulnerable to SQL injection, then we can first try the following payload:
legitimate value' and 1=1
This should result in no errors or odd behaviour regardless of any SQL injection that is present because 1=1
is always true and so the output depends only on the first part of the query. Next, we change the condition so that is always false:
legitimate value' and 1=2
This query will always fail if the application is vulnerable to SQL injection, since the condition 1=2
is always false. If we now observe a change in the behaviour of the application as compared to when the condition was 1=1
, we can be fairly certain that the target is vulnerable to blind SQL injection.
The second way to test for blind SQL injections is by using time delays. The functions which trigger time delays are different across the various database engines, but the basic premise is the same - we send a payload which should cause a certain delay and then we check if the response time is close to the delay we specified. Following is a list of the various delay-causing payloads one can use with different database engines.
Database | Function | Example Payload | Note |
---|---|---|---|
MySQL | sleep(seconds) |
1' + sleep(5) 1' and sleep(5) 1' && sleep(5) 1' | sleep(5) |
|
PostgreSQL | pg_sleep(seconds) |
1' || pg_sleep(5) |
Can only be done with the || operator. |
MSSQL | WAITFOR DELAY 'hours:minutes:seconds' |
1' WAITFOR DELAY '0:0:10' |
Notice the lack of a logical or any other operator. |
Oracle | dbms_pipe.receive_message((random string),seconds) |
dbms_pipe.receive_message(('a'),10) |
While obtaining data by manually exploiting blind SQL injection is possible, the process is very arduous and basically consists of asking a myriad yes-or-no questions about the data in an attempt to guess what it is.
sqlmap is the go-to tool for automating SQL injection detection and exploitation.
While very useful, `sqlmap` is far from stealthy and generates a lot of traffic.
Its basic syntax is as follows:
sqlmap -u <full URL> -p <parameter>
The full URL
is the exact URL of the web page we are testing for injection, including any parameters that may be in it. The parameter
argument specifies the parameter we want to test for injection.
One of its best features is the ability to specify a request from a file. This is particularly useful because one can save an intercepted request through BurpSuite and then pass it to sqlmap
which will automatically detect any possible injection points in it.
To pass the file to sqlmap
we use the -r
option:
sqlmap -r <file path>